package com.lambert.gingko.watermark.strategy.impl;

import com.lambert.gingko.watermark.annotation.FileProcessor;
import com.lambert.gingko.watermark.enums.FileType;
import com.lambert.gingko.watermark.model.WatermarkConfig;
import com.lambert.gingko.watermark.strategy.AbstWatermarkProcessor;
import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.vml.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STTrueFalse;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.stream.Stream;

/**
 * Word文件水印处理器
 * @author lambert
 * @since  2025/08/31
 */
@FileProcessor(FileType.WORD)
@Slf4j
public class WordWatermarkProcessor extends AbstWatermarkProcessor {

    // 一个字平均长度，单位pt，用于：计算文本占用的长度（文本总个数*单字长度）
    private static  final Integer widthPerWord = 10;
    // 与顶部的间距
    private static Integer styleTop = 0;
    // 文本旋转角度
    private static final String styleRotation = "45";


    @Override
    protected void doProcess(InputStream is, File outputFile , String extension, WatermarkConfig config) throws Exception {
        try (XWPFDocument doc = new XWPFDocument(is);
             FileOutputStream os = new FileOutputStream(outputFile)) {

            // 根据配置选择水印位置：页眉/页脚/正文
            switch (config.getContentLocation()) {
                case HEADER:
                    addWatermarkToHeader(doc, config);
                    break;
                case FOOTER:
                    addWatermarkToFooter(doc, config);
                    break;
                case CONTENT:
                    addWatermarkToContent(doc, config);
                    break;
            }
            // 写入输出文件
            doc.write(os);
        }
    }

    @Override
    public FileType getSupportedType() {
        return FileType.WORD;
    }


    /**
     * 添加水印到页眉
     */
    private void addWatermarkToHeader(XWPFDocument doc, WatermarkConfig config) {
        XWPFHeaderFooterPolicy policy = doc.getHeaderFooterPolicy();
        if (policy == null) {
            policy = doc.createHeaderFooterPolicy();
        }
        XWPFHeader header = policy.createHeader(XWPFHeaderFooterPolicy.DEFAULT);
        addWatermarkToContainer(header.createParagraph(), config);
    }

    /**
     * 添加水印到页脚
     */
    private void addWatermarkToFooter(XWPFDocument doc, WatermarkConfig config) {
        XWPFHeaderFooterPolicy policy = doc.getHeaderFooterPolicy();
        if (policy == null) {
            policy = doc.createHeaderFooterPolicy();
        }
        XWPFFooter footer = policy.createFooter(XWPFHeaderFooterPolicy.DEFAULT);
        addWatermarkToContainer(footer.createParagraph(), config);
    }

    /**
     * 给文档添加水印
     * 此方法可以单独使用
     * @param doc 需要被处理的docx文档对象
     * @param config 水印配置
     */
    public void addWatermarkToContent(XWPFDocument doc,WatermarkConfig config){
        // 把整页都打上水印
        for (int lineIndex = -5; lineIndex < 20; lineIndex++) {
            styleTop = 100 * lineIndex;
            waterMarkDocXDocument(doc,config);
        }
    }



    /**
     * 为文档添加水印
     * @param doc 需要被处理的docx文档对象
     * @param config 水印配置
     */
    public void waterMarkDocXDocument(XWPFDocument doc,WatermarkConfig config) {
        String customText = config.getText();
        // 水印文字之间使用8个空格分隔
        customText = customText + repeatString(" ", 8);
        // 一行水印重复水印文字次数
        customText = repeatString(customText, 10);
        // 如果之前已经创建过 DEFAULT 的Header，将会复用
        XWPFHeader header = doc.createHeader(HeaderFooterType.DEFAULT);
        int size = header.getParagraphs().size();
        if (size == 0) {
            header.createParagraph();
        }
        CTP ctp = header.getParagraphArray(0).getCTP();
        byte[] rsiDr = doc.getDocument().getBody().getPArray(0).getRsidR();
        byte[] rsiDrDefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
        ctp.setRsidP(rsiDr);
        ctp.setRsidRDefault(rsiDrDefault);
        CTPPr ppr = ctp.addNewPPr();
        ppr.addNewPStyle().setVal("Header");
        // 开始加水印
        CTR ctr = ctp.addNewR();
        CTRPr ctrpr = ctr.addNewRPr();
        ctrpr.addNewNoProof();
        CTGroup group = CTGroup.Factory.newInstance();
        CTShapetype shapeType = group.addNewShapetype();
        CTTextPath shapeTypeTextPath = shapeType.addNewTextpath();
        shapeTypeTextPath.setOn(STTrueFalse.T);
        shapeTypeTextPath.setFitshape(STTrueFalse.T);
        CTLock lock = shapeType.addNewLock();
        lock.setExt(STExt.VIEW);
        CTShape shape = group.addNewShape();
        shape.setId("PowerPlusWaterMarkObject");
        shape.setSpid("_x0000_s102");
        shape.setType("#_x0000_t136");
        // 设置形状样式（旋转，位置，相对路径等参数）
        shape.setStyle(getShapeStyle(customText,config));
        shape.setFillcolor(toHexColor(config.getColor()));
        CTFill fill =  shape.addNewFill();
        fill.setOpacity(String.valueOf(config.getOpacity()));
        // 字体设置为实心
        shape.setStroked(STTrueFalse.FALSE);
        // 绘制文本的路径
        CTTextPath shapeTextPath = shape.addNewTextpath();
        // 设置文本字体与大小
        Font font = config.getFont();
        shapeTextPath.setStyle("font-family:" + font.getFamily() + ";font-size:" + font.getSize());
        shapeTextPath.setString(customText);
        CTPicture pict = ctr.addNewPict();
        pict.set(group);
    }

    /**
     * 构建Shape的样式参数
     * @param customText 水印文字
     * @param config 水印配置
     * @return 水印样式
     */
    private String getShapeStyle(String customText,WatermarkConfig config) {
        StringBuilder sb = new StringBuilder();
        // 文本path绘制的定位方式
        sb.append("position: ").append("absolute");
        // 计算文本占用的长度（文本总个数*单字长度）
        sb.append(";width: ").append(customText.length() * widthPerWord).append("pt");
        // 字体高度
        sb.append(";height: ").append("20pt");
        sb.append(";z-index: ").append("-251654144");
        sb.append(";mso-wrap-edited: ").append("f");
        // 设置水印的间隔，这是一个大坑，不能用top,必须要margin-top。
        sb.append(";margin-top: ").append(styleTop);
        sb.append(";mso-position-horizontal-relative: ").append("page");
        sb.append(";mso-position-vertical-relative: ").append("page");
        sb.append(";mso-position-vertical: ").append("left");
        sb.append(";mso-position-horizontal: ").append("center");
        sb.append(";rotation: ").append(config.getAngle());
        return sb.toString();
    }

    /**
     * 将指定的字符串重复repeats次.
     */
    private String repeatString(String pattern, int repeats) {
        StringBuilder buffer = new StringBuilder(pattern.length() * repeats);
        Stream.generate(() -> pattern).limit(repeats).forEach(buffer::append);
        return new String(buffer);
    }

    /**
     * 向页眉/页脚容器添加水印（简单文本）
     */
    private void addWatermarkToContainer(XWPFParagraph para, WatermarkConfig config) {
        //para.setAlignment(getParagraphAlignment(config.getPosition().getPosition()));
        XWPFRun run = para.createRun();
        run.setText(config.getText());
        run.setFontFamily(config.getFont().getFamily());
        run.setFontSize(config.getFont().getSize());
        run.setColor(toHexColor(config.getColor()));
        run.setBold(config.getFont().isBold());
    }

}
    